package fr.janalyse.series.view

import fr.janalyse.series._
import collection.JavaConversions._

import java.io.File

import java.awt.Color
import java.awt.BasicStroke
import java.awt.geom.Ellipse2D

import org.jfree.chart.plot.Plot
import org.jfree.chart.JFreeChart
import org.jfree.chart.ChartFactory
import org.jfree.chart.plot.XYPlot
import org.jfree.chart.axis.NumberAxis
import org.jfree.chart.axis.AxisLocation
import org.jfree.data.xy.XYDataset
import org.jfree.chart.labels.XYToolTipGenerator
import org.jfree.data.DomainOrder
import org.jfree.data.general.DatasetChangeListener
import org.jfree.data.general.DatasetGroup
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer
import org.jfree.chart.renderer.xy.XYAreaRenderer

case class StackedSeriesDataSet(series: Array[Series[Cell]]) extends org.jfree.data.xy.TableXYDataset {

  var datasetGroup: DatasetGroup = _

  // TODO : Temporary hack, aligned series cells is mandatory for this kind of charts !!!
  override def getItemCount(): Int = series.map(_.size).min
  
  override def getDomainOrder() = DomainOrder.NONE

  override def getItemCount(seriesIndex: Int): Int = series(seriesIndex).size

  override def getX(seriesIndex: Int, item: Int): Number = series(seriesIndex).get(item).time

  override def getXValue(seriesIndex: Int, item: Int): Double = series(seriesIndex).get(item).time

  override def getY(seriesIndex: Int, item: Int): Number = getValue(seriesIndex, item)

  override def getYValue(seriesIndex: Int, item: Int): Double = getValue(seriesIndex, item)

  override def getSeriesCount(): Int = series.size

  override def getSeriesKey(seriesIndex: Int): Comparable[String] = series(seriesIndex).alias

  override def indexOf(seriesKey: Comparable[_]): Int = series.indexWhere(_.alias == seriesKey)

  override def addChangeListener(listener: DatasetChangeListener) {}

  override def removeChangeListener(listener: DatasetChangeListener) {}

  override def getGroup(): DatasetGroup = datasetGroup

  override def setGroup(group: DatasetGroup) { this.datasetGroup = group }

  def getValue(seriesIndex: Int, item: Int): Double = series(seriesIndex).get(item).value

}

object StackedChart {
  def apply(seriesArray: Series[Cell]*)(implicit config: ChartConfig) = new StackedChart(seriesArray.toIterable, chartConfig=config)
  def apply(seriesList: Iterable[Series[Cell]])(implicit config: ChartConfig) = new StackedChart(seriesList, chartConfig=config)
  def apply(title: String, seriesArray: Series[Cell]*)(implicit config: ChartConfig) = new StackedChart(seriesArray.toIterable, Some(title), chartConfig=config)
  def apply(title: String, seriesList: Iterable[Series[Cell]])(implicit config: ChartConfig) = new StackedChart(seriesList, Some(title), chartConfig=config)
}

class StackedChart(
  val seriesList: Iterable[Series[Cell]],
  val title: Option[String] = None,
  val chartConfig: ChartConfig = ChartConfig()) extends ChartCommon {


  private val jchart = ChartFactory.createTimeSeriesChart(null, null, null, null, false, false, false)
  private val jplot = jchart.getPlot().asInstanceOf[XYPlot]

  title foreach { jfree.setTitle(_) }

  val scaleManager = chartConfig.scaleManager()

  jplot.setBackgroundPaint(new Color(220, 220, 220));
  jplot.setDomainGridlinePaint(Color.white);
  jplot.setRangeGridlinePaint(Color.white);

  for ((k, v) <- hints) jchart.getRenderingHints().put(k, v)
  jchart.setAntiAlias(true)
  jchart.setTextAntiAlias(true)

  //val preparedSeries = align(seriesList) // TODO 
  val preparedSeries = seriesList
  
  val renderer = new org.jfree.chart.renderer.xy.StackedXYAreaRenderer2() {
    for (i <- 0 until preparedSeries.size) {
      setSeriesFillPaint(i, Color.white)
      setSeriesPaint(i, colorPool.take)
      setSeriesStroke(i, basicStroke)
      setSeriesOutlineStroke(i, outlineBasicStroke)
      setSeriesShape(i, shape)
    }
  }
  val dataset = StackedSeriesDataSet(preparedSeries.toArray)
  
  jplot.setRenderer(0, renderer)
  jplot.setDataset(0, dataset)

  protected val jfree = new JFreeChart(null, null, jplot, chartConfig.showLegend)
}
  
